//
//  main.cpp
//  CppDemo
//
//  Created by 蒋益杰 on 16/5/19.
//  Copyright © 2016年 com.ed. All rights reserved.
//

#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>

#include <unistd.h>

#include <signal.h>
#include <stdio.h>
#include <termios.h>

#include "STLUsage.hpp"
#include "Picture.hpp"

#include "ReverseString.hpp"
#include "LeetcodeQuestions.hpp"

#include <assert.h>
#include "endian.c"
#include "audio_parser.c"

#include "CQueue.hpp"

#include <malloc/malloc.h>

#include "StringDemo.hpp"
#include "btree.hpp"

using namespace std;

template <typename T>
struct display {
    void operator() (const T& x) const
    {
        std::cout << x << ' ';
    }
};

class even_by_two {
public:
    int operator() () const
    {
        return _x += 2;
    }
private:
    static int _x;
};

int even_by_two::_x = 0;

#define BUFFSIZE            4096
#define MAX_PASS_LEN        8

char *getpass(const char *prompt);

const char *init[] = {"sss", "ttttt", "212"};

int simplest_yuv420_graybar(int width, int height, int ymin, int ymax, int barnum, char *url_out);

int main(int argc, const char * argv[]) {
    
    /*
    Picture p(init, 3);
    cout << p << endl;
//    Picture q = p;
//    cout << q << endl;
    
    Picture q = frame(p);
    cout << q << endl;
    
    Picture r = p | q;
    cout << r << endl;
    
    Picture s = q & r;
    cout << s << endl << frame(s) << endl;
    
    char st[] = "abcdef";
    int len = sizeof(st) / sizeof(char) - 1;
    leftshift(st, len, 2);
    assert(strcmp(st, "cdefab") == 0);
    
#pragma mark - reverse testcase
    
    RListNode *head = new RListNode(100);
    RListNode *node1 = new RListNode(1);
    RListNode *node2 = new RListNode(2);
    RListNode *node3 = new RListNode(3);
    
    head->next = node1;
    node1->next = node2;
    node2->next = node3;
    node3->next = NULL;
    
    RListNode *reverseHead = reverseList(head);
    assert(reverseHead->value == 3);
    
    RListNode *reverseHead1 = reverseList(NULL);
    assert(reverseHead1 == NULL);
    
    RListNode *node_single = new RListNode(2);
    RListNode *reverseHead2 = reverseList(node_single);
    assert(reverseHead2->value == 2);
    
    delete head;
    delete node1;
    delete node2;
    delete node3;
    delete node_single;
    
    cout<< " sum = " << getSum(6, 2) << endl;
    
    vector<int> vec1;
    vector<int> vec2;
    vec2.push_back(1);
    
    vector<int> vec3 = intersection(vec1, vec2);
    
    vector<int> array = {9};
    vector<int> res1 = plusOne(array);
    
    char c = findTheDifference("abcd", "abcde");
    
    int idx = firstUniqChar("");
    cout << "idx = " << idx << endl;
    
    computeArea(-2, -2, 2, 2, -2, -2, 2, 2);
    
    vector<int> strvec = {1};
    rightshfit(strvec, 0);
    cout<< " size = " << strvec.size() << endl;
    
    
    string res122 = removeDuplicateLetters("bcabc");
    cout<< " string = " << res122 << endl;
    */
    /*
    TreeNode *root1 = new TreeNode(1);
    TreeNode *tnode2 = new TreeNode(2);
    TreeNode *tnode3 = new TreeNode(3);
    TreeNode *tnode4 = new TreeNode(4);
    TreeNode *tnode5 = new TreeNode(5);
    TreeNode *tnode6 = new TreeNode(6);
    TreeNode *tnode7 = new TreeNode(7);
    TreeNode *tnode8 = new TreeNode(8);
    root1->left = tnode2;
    root1->right = tnode3;
    tnode2->left = tnode4;
    
    tnode3->left = tnode5;
    tnode3->right = tnode8;
    tnode5->left = tnode6;
    tnode5->right = tnode7;
    
    vector<int> vec_right = rightSideView(root1);
    cout << endl;
    
    delete root1;
    delete tnode2;
    delete tnode3;
    delete tnode4;
    delete tnode5;
    delete tnode6;
    delete tnode7;
    delete tnode8;
     */
    
//    RandomListNode *ran1 = new RandomListNode(1);
//    RandomListNode *ran2 = new RandomListNode(2);
//    RandomListNode *ran3 = new RandomListNode(3);
//    RandomListNode *ran4 = new RandomListNode(4);
//    RandomListNode *ran5 = new RandomListNode(5);
//    
//    ran1->next = ran2;
//    ran1->random = ran3;
//    
//    ran2->next = ran3;
//    ran2->random = ran1;
//    
//    ran3->next = ran4;
//    ran3->random = ran2;
//    
//    ran4->next = ran5;
//    ran4->random = ran2;
//    
//    ran5->random = ran4;
//    
//    RandomListNode *resultRan = copyRandomList(ran1);
    
//    cout << "result : " << is_big_endian() << ", other result: " << is_big_endian1() << endl;
//    cout << "my MY_ENDIANNESS : " << MY_ENDIANNESS << endl;
//    
//    unsigned int x = 0x12345678;
//    x = BigToLittleEndian32(x);
//    printf("after:0x%0x\n", x);
    
//    ListNode *head = new ListNode(1);
//    ListNode *node2 = new ListNode(2);
//    ListNode *node3 = new ListNode(3);
//    ListNode *node4 = new ListNode(4);
//    head->next = node2;
//    node2->next = node3;
//    node3->next = node4;
//    
//    TreeNode *treenode = sortedListToBST(head);
//    cout << endl;
//    
////    simplest_yuv420_graybar(640, 360,0,255,10, "/Users/jiangyijie/Desktop/graybar_640x360.yuv");
//    vector<int> vecint = {};
//    int min = findMin(vecint);
//    cout << "min: " << min << endl;
//    
////    simplest_aac_parser("/Users/jiangyijie/Desktop/nocturne.aac");
//    
//    TreeNode *root1 = new TreeNode(1);
//    TreeNode *tnode2 = new TreeNode(2);
//    TreeNode *tnode3 = new TreeNode(3);
//    TreeNode *tnode4 = new TreeNode(4);
//    TreeNode *tnode5 = new TreeNode(5);
//    
//    root1->left = tnode2;
//    root1->right = tnode3;
//    tnode3->left = tnode4;
//    
//    tnode3->left = tnode4;
//    tnode3->right = tnode5;
//    
//    Codec codec;
//    string result = codec.serialize(root1);
//    TreeNode *node = codec.deserialize("1 2 3 # # 4 5 # # # #");
//    
//    vector<pair<int, int>> people = {{7,0}, {4,4}, {7,1}, {5,0}, {6,1}, {5,2}};
//    reconstructQueue(people);
//    vector<string> sss = {"eat", "tea", "tan", "ate", "nat", "bat"};
//    auto ressss = groupAnagrams(sss);
//    
//    for (auto veccc : ressss) {
//        for (auto str : veccc) {
//            cout << str << ", ";
//        }
//        cout << endl;
//    }
    
//    int data[] = {7, 5, 6, 4};
//    inversePairs(data, 4);
//    char str[22] = "we are happy.";
//    replaceBlank(str, 22);
//    
//    cout << "str = " << str << endl;
    
//    CQueue<int> cQ;
//    cQ.appendTail(1);
//    cQ.print();
//    cQ.appendTail(2);
//    cQ.print();
//    cQ.deleteHead();
//    cQ.print();
//    cQ.deleteHead();
//    cQ.print();
    
//    int data[] = {1, 2, 1, 1, 1, 4, 4, 4, 4, 6, 6, 6, 6};
//    int index = findNumAppearOnce(data, 13);
    
//    const char *p = "ABCDABD";
//    int next[7];
//    makeNext(p, next);

//    int i;
//    int next[20]={0};
//    char T[] = "ddaabcdabdabaadsss";
//    char P[] = "abcdabd";
//    printf("%s\n",T);
//    printf("%s\n",P );
//    // makeNext(P,next);
//    int resssIdx = kmp(T,P,next);
//    for (i = 0; i < strlen(P); ++i)
//    {
//        printf("%d ",next[i]);
//    }
//    printf("\n");
    
//    readFile();
    
    BiTree *btree = new BiTree();
    btree->insert(5);
    btree->insert(2);
    btree->insert(9);
    btree->insert(8);
    btree->insert(7);
    btree->insert(3);
    btree->insert(4);
    btree->insert(1);
    btree->insert(6);
    
    btree->display();
    
    btree->remove(4);
    btree->display();
    
    btree->remove(6);
    btree->display();
    
    btree->remove(7);
    btree->display();
    
    btree->remove(1);
    btree->display();

    btree->remove(3);
    btree->display();
    return 0;
}

char *getpass(const char *prompt)
{
    static char buf[MAX_PASS_LEN + 1];
    char *ptr;
    sigset_t sig, osig;
    struct termios ts, ots;
    FILE *fp;
    int c;
    
    if ((fp = fopen(ctermid(NULL), "r+")) == NULL) {
        return NULL;
    }
    setbuf(fp, NULL);
    
    sigemptyset(&sig);
    sigaddset(&sig, SIGINT);
    sigaddset(&sig, SIGTSTP);
    sigprocmask(SIG_BLOCK, &sig, &osig);
    
    tcgetattr(fileno(fp), &ts);
    ots = ts;
    ts.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
    tcsetattr(fileno(fp), TCSAFLUSH, &ts);
    fputs(prompt, fp);
    
    ptr = buf;
    while ((c = getc(fp)) != EOF && c != '\n') {
        if (ptr < &buf[MAX_PASS_LEN]) {
            *ptr++ = c;
        }
    }
    *ptr = 0;
    putc('\n', fp);
    
    tcsetattr(fileno(fp), TCSAFLUSH, &ots);
    sigprocmask(SIG_SETMASK, &osig, NULL);
    fclose(fp);
    return buf;
}

int simplest_yuv420_graybar(int width, int height, int ymin, int ymax, int barnum, char *url_out) {
    int barwidth;
    float lum_inc;
    unsigned char lum_temp;
    
    int uv_width, uv_height;
    FILE *fp = NULL;
    unsigned char *data_y = NULL;
    unsigned char *data_u = NULL;
    unsigned char *data_v = NULL;
    
    int t = 0, i = 0, j = 0;
    barwidth = width / barnum;
    lum_inc = ((float) (ymax - ymin)) / (float)(barnum - 1);
    uv_width = width / 2;
    uv_height = height / 2;
    
    data_y = (unsigned char *)malloc(width * height);
    data_u = (unsigned char *)malloc(uv_width * uv_height);
    data_v = (unsigned char *)malloc(uv_width * uv_height);
    
    if ((fp = fopen(url_out, "wb+")) == NULL) {
        cerr << "can not create file" << endl;
        return -1;
    }
    
    for (t = 0; t < (width / barwidth); ++t) {
        lum_temp = ymin + (char)(t * lum_inc);
    }
    
    //Gen Data
    for(j = 0; j < height; j++){
        for(i = 0; i < width; i++){
            t = i/barwidth;
            lum_temp = ymin + (char)(t*lum_inc);
            data_y[j*width+i] = lum_temp;
        }
    }
    
    for(j=0;j<uv_height;j++){
        for(i=0;i<uv_width;i++){
            data_u[j*uv_width+i]=128;
        }
    }
    for(j=0;j<uv_height;j++){
        for(i=0;i<uv_width;i++){
            data_v[j*uv_width+i]=128;
        }
    }
    
    fwrite(data_y, width * height, 1, fp);
    fwrite(data_u, uv_height * uv_width, 1, fp);
    fwrite(data_v, uv_width * uv_height, 1, fp);
    fclose(fp);
    free(data_y);
    free(data_u);
    free(data_v);
    
//    int data[] = {7, 5, 6, 4};
//    int count_inversePairs = inversePairs(data, 4);
    
    
    return 0;
}

